function Point(position, w) {
  this.position = position;
  this.w = w;
}
function TIN(indices, vertexes, adjointTINs, flag = undefined) {
  this.indices = indices;
  this.vertexes = vertexes;
  this.adjointTINs = adjointTINs || [null, null, null];
  this.flag = flag;
}
function arrayMaxValue(array, comparator = (a, b) => a < b) {
  if (!Array.isArray(array) || array.length === 0) {
    return 0;
  }
  let max = Number.MIN_VALUE;
  for (let i = 0, length = array.length; i < length; i++) {
    if (comparator(max, array[i])) {
      max = array[i];
    }
  }
  return max;
}
function arrayMinValue(array, comparator = (a, b) => a > b) {
  if (!Array.isArray(array) || array.length === 0) {
    return 0;
  }
  let min = Number.MAX_VALUE;
  for (let i = 0, length = array.length; i < length; i++) {
    if (comparator(min, array[i])) {
      min = array[i];
    }
  }
  return min;
}
function defaultValue(a, b) {
  if (a !== undefined && a !== null) {
    return a;
  }
  return b;
}

function defined(value) {
  return value !== undefined && value !== null;
}

function Cartesian3(x, y, z) {
  this.x = defaultValue(x, 0.0);
  this.y = defaultValue(y, 0.0);
  this.z = defaultValue(z, 0.0);
}

function isAdjoinTINs(tin1, tin2) {
  const indices1 = tin1.indices,
    indices2 = tin2.indices;
  const filterList = indices1.filter(
    (indice) => indices2.indexOf(indice) !== -1
  );
  const flag = filterList.length === 2;
  const vertexIdxs = indices1.filter(
    (indice) => filterList.indexOf(indice) === -1
  );
  return {
    flag,
    vertexIdx: vertexIdxs.length === 1 ? vertexIdxs[0] : null,
  };
}

function queryAdjoinTINs(tin, tinSet = []) {
  const adjointTINs = [null, null, null];
  if (!defined(tin)) return adjointTINs;
  const length = tinSet.length;
  const indices = tin.indices;
  let counter = 0;
  for (let i = 0; i < length; i++) {
    const curTIN = tinSet[i];
    if (tin === curTIN) {
      continue;
    }
  }
  return adjointTINs;
}

function createTINSet(workerData) {
  if (!defined(workerData)) return [];
  try {
    const tinSet = [];
    const { indieList, vertexList, altitudeList } = workerData || {};
    const maxAltitude = arrayMaxValue(altitudeList),
      minAltitude = arrayMinValue(altitudeList);
    for (let i = 0; i < indieList.length; i += 3) {
      const idx_1 = indieList[i + 2],
        idx_2 = indieList[i + 1],
        idx_3 = indieList[i];
      const p1 = new Cartesian3(
          vertexList[idx_1 * 3],
          vertexList[idx_1 * 3 + 1],
          vertexList[idx_1 * 3 + 2]
        ),
        p2 = new Cartesian3(
          vertexList[idx_2 * 3],
          vertexList[idx_2 * 3 + 1],
          vertexList[idx_2 * 3 + 2]
        ),
        p3 = new Cartesian3(
          vertexList[idx_3 * 3],
          vertexList[idx_3 * 3 + 1],
          vertexList[idx_3 * 3 + 2]
        );
      const [height1, height2, height3] = [
        altitudeList[i + 2],
        altitudeList[i + 1],
        altitudeList[i],
      ];
      const vertex1 = new Point(p1, height1),
        vertex2 = new Point(p2, height2),
        vertex3 = new Point(p3, height3);
      const tin = new TIN([idx_1, idx_2, idx_3], [vertex1, vertex2, vertex3]);
      tinSet.push(tin);
    }
    for (let i = 0; i < tinSet.length; i++) {
      const curTIN = tinSet[i];
      tinSet[i].adjointTINs = queryAdjoinTINs(curTIN, tinSet);
    }
    return {
      tinSet: tinSet,
      maxAltitude: maxAltitude,
      minAltitude: minAltitude,
    };
  } catch (err) {
    return {};
  }
}

export default createTINSet;
